package com.xaslsoft.xaslsoft.device.net;

import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.socket.nio.ChannelHandler;
import cn.hutool.socket.nio.NioClient;
import com.xaslsoft.xaslsoft.device.utils.ByteUtils;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * TcpClient
 */
public class TcpClient implements ChannelHandler {
	public static final Map<String, NioClient> SOCKET_CHANNELS = new HashMap<>();
	public static final Map<String, TcpChannelHandler> SOCKET_HANDLER = new HashMap<>();

	/**
	 * 连接Tcp服务器
	 *
	 * @param ip
	 * @param port
	 * @param channelHandler
	 */
	public void connect(String ip, int port, TcpChannelHandler channelHandler) throws IORuntimeException {
		NioClient client = new NioClient(ip, port);
		client.setChannelHandler(this::handle);
		client.listen();
		SOCKET_CHANNELS.put(ip, client);
		SOCKET_HANDLER.put(ip, channelHandler);
	}

	/**
	 * 向tcp服务器发送指令
	 *
	 * @param ip
	 * @param hex
	 */
	public void sendHexStr(String ip, String hex) {
		System.out.println("发送数据->ip= " + ip + ", hex = " + hex);
		SOCKET_CHANNELS.get(ip).write(BufferUtil.create(ByteUtils.hexStr2Byte(hex)));
		ThreadUtil.sleep(200);
	}

	@Override
	public void handle(SocketChannel socketChannel) throws IOException {
		String address = socketChannel.getRemoteAddress().toString();
		String ip = StrUtil.subBetween(address, "/", ":");
		TcpChannelHandler handler = SOCKET_HANDLER.get(ip);
		if (!Objects.isNull(handler)) {
			handler.onReceive(ip, socketChannel, procData(socketChannel));
		}
	}

	/**
	 * 断开释放TCP连接
	 *
	 * @param ip
	 */
	public void closeConnect(String ip) {
		NioClient client = SOCKET_CHANNELS.get(ip);
		if (!Objects.isNull(client)) {
			client.close();
		}
	}

	/**
	 * 数据解析转换
	 *
	 * @param channel
	 * @return
	 * @throws IOException
	 */
	private String procData(SocketChannel channel) throws IOException {
		ByteBuffer readBuffer = ByteBuffer.allocate(1024);
		//从channel读数据到缓冲区
		int readBytes = channel.read(readBuffer);
		String body = "";
		if (readBytes > 0) {
			readBuffer.flip();
			// 要读取的字节长度
			byte[] bytes = new byte[readBuffer.remaining()];
			//将缓冲区的数据读到bytes数组
			readBuffer.get(bytes);
			body = ByteUtils.byteArrayToHexString(bytes);
			System.out.println("channel = " + channel + ", hex = " + body);
		} else if (readBytes < 0) {
			channel.close();
		}
		return body;
	}


	public interface TcpChannelHandler {
		/**
		 * TCP客户端监听服务端消息
		 *
		 * @param ip
		 * @param channel
		 * @param hex
		 * @throws IOException
		 */
		void onReceive(String ip, SocketChannel channel, String hex) throws IOException;

	}

}
